package com.dingwen.treasure.task.quartz.controller;

import cn.hutool.core.util.StrUtil;
import com.dingwen.treasure.base.controller.BaseViewController;
import com.dingwen.treasure.base.enums.QuartzStateEnum;
import com.dingwen.treasure.base.exception.BusinessException;
import com.dingwen.treasure.base.pojo.vo.Result;
import com.dingwen.treasure.jpa.service.QuartzInfoService;
import com.dingwen.treasure.jpa.service.QuartzLogService;
import com.dingwen.treasure.model.entity.jpa.QuartzInfo;
import com.dingwen.treasure.model.entity.jpa.QuartzLog;
import com.dingwen.treasure.task.quartz.dto.QuartzInfoStateDTO;
import com.dingwen.treasure.task.quartz.manager.QuartzJobManager;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.quartz.CronExpression;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Optional;

/**
 * 　QuartzController
 * 　@author dingwen
 * 　@date 2022/5/11$
 */
@Api(tags = "定时任务")
@RestController
@Slf4j
@RequestMapping("quartz")
public class QuartzController implements BaseViewController {

    /**
     * 定时任务服务
     */
    @Resource
    private QuartzInfoService quartzInfoService;

    /**
     * 定时任务日志服务
     */
    @Resource
    private QuartzLogService quartzLogService;


    /**
     * quartzManager
     */
    @Resource
    private QuartzJobManager quartzManager;


    /**
     * 获取所有执行中的任务列表
     *
     * @return {@link Result}
     */
    @ApiOperation(value = "获取所有执行中的任务列表")
    @GetMapping("/job/list")
    public Result<?> findAllForJob() {
        return success(quartzManager.getAllJob());
    }

    /**
     * 获取定时任务信息列表
     *
     * @return {@link Result}
     */
    @ApiOperation(value = "获取定时任务信息列表")
    @GetMapping("/info/list")
    public Result<List<QuartzInfo>> findAllForInfo() {
        QuartzInfo quartzInfo = QuartzInfo.builder().build();
        return success(quartzInfoService.findAll(Example.of(quartzInfo)));
    }

    /**
     * 添加一个定时任务
     *
     * @param quartzInfo quartzInfo
     * @return {@link Result}
     */
    @ApiOperation(value = "添加一个定时任务信息")
    @PostMapping("info")
    public Result<?> addQuartzInfo(@RequestBody QuartzInfo quartzInfo) {
        Assert.isTrue(CronExpression.isValidExpression(quartzInfo.getCronExpression()), "cron表达式错误");
        // 添加quartzInfo
        QuartzInfo quartzInfoForAdapter = quartzManager.adapterQuartzInfo(quartzInfo);
        QuartzInfo quartzInfoForDb = quartzInfoService.save(quartzInfoForAdapter);
        if (quartzInfoForDb.getState().equals(QuartzStateEnum.ENABLE)) {
            quartzManager.addJob(quartzInfoForDb);
        }
        return success();
    }


    /**
     * 修改运行中的任务信息
     *
     * @param quartzInfo info
     * @return {@link Result}
     */
    @ApiOperation(value = "修改运行中的任务信息")
    @PutMapping("job")
    public Result<?> modifyQuartzJob(@RequestBody QuartzInfo quartzInfo) {
        Assert.isTrue(StrUtil.isEmpty(quartzInfo.getCronExpression()) || CronExpression.isValidExpression(quartzInfo.getCronExpression()), "cron表达式错误");
        quartzManager.modifyJob(quartzInfo);
        return success();
    }

    /**
     * 立即执行
     *
     * @param quartzId id
     * @return {@link Result}
     */
    @ApiOperation("立即执行")
    @GetMapping("executor/now/{quartzId}")
    public Result<?> executorNow(@PathVariable Long quartzId) {
        quartzManager.startJobNow(quartzId);
        return success();
    }

    /**
     * 分页查询任务执行日志
     *
     * @param pageNumber 页码
     * @param pageSize   页面大小
     * @return {@link Result}<{@link ?}>
     */
    @ApiOperation("分页查询所有日志信息")
    @GetMapping("log/page")
    public Result<?> findAllForLog(@RequestParam("pageNumber") Integer pageNumber,
                                   @RequestParam("pageSize") Integer pageSize) {
        Pageable pageable = PageRequest.of(pageNumber - 1, pageSize.intValue());
        Page<QuartzLog> quartzLogPage = quartzLogService.page(pageable);
        return success(quartzLogPage);
    }

    /**
     * 修改定时任务状态
     *
     * @param quartzInfoState 任务状态
     * @return {@link Result}<{@link ?}>
     * @throws BusinessException 异常
     */
    @ApiOperation("修改定时任务状态")
    @ApiImplicitParam(value = "任务状态DTO", name = "quartzInfoState", type = "body", required = true)
    @PutMapping("state")
    public Result<?> modifyQuartzInfoState(@RequestBody QuartzInfoStateDTO quartzInfoState) {
        quartzManager.modifyJobState(quartzInfoState);
        return success();
    }


    /**
     * 删除定时任务
     *
     * @return {@link Result}<{@link ?}>
     */
    @ApiOperation("删除定时任务")
    @DeleteMapping("")
    public Result<?> removeQuartz(@RequestParam @NotNull Long quartzId) {

        Optional<QuartzInfo> quartzInfoOptional = quartzInfoService.findById(quartzId);
        String message = "quartzId: {},定时任务不存在";
        Assert.notNull(quartzInfoOptional.isPresent(), StrUtil.format(message, quartzId));
        quartzManager.deleteJob(quartzInfoOptional.get());
        quartzInfoService.deleteById(quartzId);
        return success();
    }

}
